#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

// // pending位图在执行信号捕捉方法之前，先清0，再调用
// // 信号被处理的时候，对应的信号也会被添加到block表中，防止信号捕捉被嵌套调用
// void PrintPending()
// {
//     sigset_t set;
//     sigpending(&set);

//     for(int signo = 1;signo <= 31;signo++)
//     {
//         if(sigismember(&set,signo))
//             std::cout << "1";
//         else
//             std::cout << "0";
//     }
//     std::cout << "\n";
// }
// void handler(int signo)
// {
//     std::cout << "catch a signal, signal number: " << signo << std::endl;
//     while(true)
//     {
//         PrintPending();
//         sleep(1);
//     }
// }
// int main()
// {
//     struct sigaction act,oact;
//     memset(&oact,0,sizeof(act));
//     memset(&oact,0,sizeof(oact));

//     sigemptyset(&act.sa_mask);
//     sigaddset(&act.sa_mask,1);
//     sigaddset(&act.sa_mask,3);
//     sigaddset(&act.sa_mask,4);
//     act.sa_handler = handler;
//     sigaction(2,&act,&oact);

//     while(true)
//     {
//         std::cout << "I am a process: " << getpid() << std::endl;

//         sleep(1);
//     }

//     return 0;
// }

volatile int flag = 0;
void handler(int signo)
{
    std::cout << "catch a signal: " << signo << std::endl;
    flag = 1;
}
int main()
{
    signal(2,handler);
    // 在优化条件下，flag变量可能被直接优化到CPU内的寄存器中
    // flag变量如果放在了CPU的寄存器内则每次更改该变量时，都更改了内存中的值，所以CPU在检测时，都只会检测到CPU内的那个变量
    // 如果一直放在内存中，则以正常逻辑运行
    while(!flag);
    std::cout << "flag: " << flag << std::endl;

    std::cout << "process quit normal" << std::endl;

    return 0;
}


// // 子进程在退出时，会主动向父进程发送SIGCHLD(17)信号
// void handler(int signo)
// {
//     sleep(5);
//     pid_t rid;
//     while ((rid = waitpid(-1, nullptr, WNOHANG) > 0))
//     {
//         std::cout << "I am process: " << getpid() 
//                   << " catch a signo: " << signo 
//                   << "child process quit: " << rid 
//                   << std::endl;
//     }
// }
// int main()
// {
//     // 忽略掉子进程给父进程发送的信号
//     // 所以就可以不用wait等待父进程接收子进程，可以直接释放子进程
//     // SIGCHLD：默认处理动作是忽略，所以父进程默认忽略子进程的退出状态
//     // SIG_IGN：默认处理动作是忽略
//     // 含义：忽略父进程对SIGCHLD信号的忽略
//     signal(17,SIG_IGN);
//     // signal(17, handler);

//     for (int i = 0; i < 5; i++)
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             while (true)
//             {
//                 std::cout << "I am child process: " << getpid() << ", ppid: " << getppid() << std::endl;
//                 sleep(5);
//                 break;
//             }
//             std::cout << "child quit!!!" << getpid() << std::endl;
//             exit(0);
//         }
//         sleep(1);
//     }
//     while (true)
//     {
//         std::cout << "I am father process: " << getpid() << std::endl;
//         sleep(1);
//     }

//     return 0;
// }